"""
* Name:        peerid.py
* Purpose:     Client identification
* Author:      roee88
"""

tornadoStyleClients =   {"T": "BitTornado",
                         "A": "ABC",
                         "O": "Osprey permaseed",
                         "Q": "BTQueue",
                         "R": "Tribler",
                         "S": "Shadow's client",
                         "U": "UPnP NAT BitTorrent",
                        }

azStyleClients =         {"AZ": ("Azureus", 3, 4),
                          "UT": (u"\xb5Torrent", 3, 4),
                          "UM": (u"\xb5Torrent Mac", 3, 4),
                          "BC": ("BitComet", 4, 3),
                          "KT": ("KTorrent", 3, 4),
                          "TS": ("TorrentStorm", 3, 4),
                          "TR": ("Transmission", 3, 4),
                          "LH": ("LH-ABC", 3, 4),
                          "LS": ("LittleShoot", 3, 4),
                          "LT": ("libtorrent (rasterbar)", 3, 4),
                          "lt": ("libTorrent (rakshasa)", 3, 4),
                          "AR": ("Arctic Torrent", 3, 4),
                          "FG": ("FlashGet", 3, 4),
                          "GR": ("GetRight", 3, 2),
                          "MT": ("Moonlight", 3, 4),
                          "AG": ("Ares Galaxy", 3, 3),
                          "A~": ("Ares Galaxy", 3, 3),
                          "XT": ("XanTorrent", 3, 4),
                          "bk": ("BitKitten", 3, 4),
                          "CT": ("CTorrent", 3, 3),
                          "SN": ("ShareNET", 3, 4),
                          "BB": ("BitBuddy", 3, 4),
                          "SS": ("SwarmScope", 3, 4),
                          "BS": ("BTSlave", 3, 4),
                          "BX": ("Bittorrent X", 3, 4),
                          "TN": ("Torrent.NET", 3, 4),
                          "ZT": ("ZipTorrent", 3, 4),
                          "SZ": ("Shareaza", 3, 4),
                          "S~": ("Shareaza beta", 3, 4),
                          "CD": ("Enhanced CTorrent", 3, 4),
                          "RT": ("Retriever", 3, 4),
                          "LP": ("Lphant", 3, 4),
                          "PC": ("CacheLogic", 3, 4),
                          "AX": ("BitPump", 3, 4),
                          "ES": ("Electric Sheep", 3, 3),
                          "MP": ("MooPolice", 3, 3),
                          "qB": ("qBitTorrent", 3, 4),
                          "QT": ("Qt 4 Torrent example", 3, 4),
                          "SB": ("Swiftbit", 3, 4),
                          "UL": ("uLeecher!", 3, 4),
                          "BO": ("Bits on Wheels", 4, 5),
                          "ML": ("MLDonkey", 3, 5),
                          "BR": ("BitRocket", 3, 4),
                          "ST": ("SymTorrent", 3, 4),
                          "st": ("sharkTorrent", 3, 4),
                          "BE": ("BE (unknown)", 3, 4),
                          "PO": ("PO (unknown)", 3, 7),
                          "UR": ("UR (unknown)", 3, 7),
                          "S2": ("S2 (unknown)", 3, 7),
                          "XX": ("Xtorrent", 3, 2),
                          "AV": ("Avicora", 3, 4),
                          "BF": ("Bitflu", 3, 4),
                          "BG": ("BTG", 3, 4),
                          "DE": ("DelugeTorrent", 3, 3),
                          "EB": ("EBit", 3, 4),
                          "HL": ("Halite", 3, 3),
                          "HN": ("Hydranode", 3, 4),
                          "PD": ("Pando", 3, 4),
                          "FT": ("FoxTorrent/RedSwoosh", 3, 4),
                          "XL": ("Xunlei", 3, 4),
                          "TT": ("TouTu", 3, 4),
                          "DP": ("Propogate Data Client", 3, 4),
                          "LW": ("LimeWire", 0, 0),
                          "AT": ("Artemis", 0, 0),
                          "FC": ("FileCroc", 3, 4),
                          "GS": ("GSTorrent", 3, 4),
                          "MO": ("MonoTorrent", 3, 4),
                          "WY": ("Wyzo", 3, 4),
                          "VG": ("Vagaa", 3, 4),
                          "MR": ("Miro", 3, 4),
                          "QD": ("QQDownload", 3, 4),
                          "WT": ("BitLet", 3, 4),
                          "RZ": ("RezTorrent", 3, 4),
                          }

def DecodePeerId(name, peerid, breaks = True):
    version_str = ""
    
    # Exceptions...
    if name == "BitComet":
        return name + " " + peerid[0] + '.' + peerid[1] + peerid[2]
    if name == "BitRocket":
        return name + " " + peerid[0] + '.' + peerid[1] + "(" + peerid[2] + peerid[3] + ")"
    if name == "Transmission":
        try:
            if peerid[:2] == "00":  #XXYB
                return name + " " + "0." + peerid[2] + peerid[3]
            else:                   #XYZB
                return name + " " + peerid[0] + '.' + peerid[1] + peerid[2] + (peerid[3]=="Z" or peerid[3]=="X")*"+"
        except:
            pass
    if name == "Enhanced CTorrent" or name == "FlashGet":
        try:
            return name + " " + str(int(peerid[0] + peerid[1])) + "." + str(int(peerid[2] + peerid[3]))
        except:
            pass
        
    for c in peerid:
        if name == "BitTornado":
            if c != '-' and c.isdigit():
                version_str += (c + '.')
            elif c != '-' and c.isalpha():
               version_str += (str(ord(c)-55) + '.')
            else:
               break
        else:
            if c != '-' and c.isalnum():
                version_str += (c + '.')
            elif breaks:
                break
                   
    return name + " " + version_str[:len(version_str)-1]

def DecodeVersionString (ver_data):
    version_str = ""
    version_str += str(ord(ver_data[0])) + '.'
    version_str += str(ord(ver_data[1])/10)  + '.'
    version_str += str(ord(ver_data[1])%10)
    return version_str

def getOperaVersion(ver_data):
    version_str = ""
    for c in ver_data:
        if c.isalnum():
            version_str += c
        else:
            break
    return version_str
            
    
def GetClientName(peerid):
    # No peer id
    if peerid == None or len(peerid) < 20:
        return "No Peerid Given"
    
    ##########################################################################
    #
    # Azureus Style
    #
    ########################################################################## 
    if "Azureus" in peerid:
        return "Azureus 2.0.3.2"
    if peerid[0] == "-":
        id = peerid[1:3]
        if azStyleClients.has_key(id):
            start = azStyleClients[id][1]
            hm = azStyleClients[id][2]
            return DecodePeerId(azStyleClients[id][0], peerid[start:(start+hm)])

    ##########################################################################
    #
    # BitTornado Style
    #
    ########################################################################## 
    if peerid[:2] == "AO":
        return DecodePeerId("ABC_OKC", peerid[2:10]) 
    if peerid[:2] == "AZ":
        return DecodePeerId("BitTyrant", peerid[2:7]) 
    if tornadoStyleClients.has_key(peerid[0]):
        return DecodePeerId(tornadoStyleClients[peerid[0]], peerid[1:10])

    ##########################################################################
    #
    # Mainline Style
    #
    ##########################################################################
    if (peerid[:12] == (chr(0)*12)):
        if peerid[12] == chr(97) and peerid[13] == chr(97):
            return "Experimental 3.2.1b2"
        return "BitTorrent"
    if peerid[:5] == "Mbrst":
        return DecodePeerId("Burst!", peerid[5:10], False) 
    if peerid[:1] == "M":
        return DecodePeerId("BitTorrent", peerid[1:8], False)
    if peerid[:1] == "Q":
        return DecodePeerId("Queen Bee", peerid[1:8], False)
    
    ##########################################################################
    #
    # Simple Style
    #
    ##########################################################################
    # G3 Torrent
    if peerid[1:3] == "G3":
        return "G3 Torrent"

    if peerid[:2] == "AP":
        return "All Peers" + DecodeVersionString(peerid[2:6])

    if peerid[:3] == "DNA":
        return "BitTorrent DNA " + DecodeVersionString(peerid[3:6])
    
    # BitSpirit
    if peerid[2:4] == "BS":
        if peerid[1] == chr(0):  return "BitSpirit v1"
        if peerid[1] == chr(2):  return "BitSpirit v2"
        return "BitSpirit"
    if peerid[14:20] == "HTTPBT" or peerid[16:20] == "UDP0":
        return "BitSpirit"

    # XBT 
    if peerid[:3] == "XBT":
        return "XBT " + peerid[3] + '.' + peerid[4] + '.' + peerid[5]

    # Rufus 
    if peerid[2:4] == "RS":
        for c in peerid[4:13]: 
            if c.isalnum() or c == chr(0):
                rufus_chk = True
            else:
                rufus_chk = False
                break

        if rufus_chk:
            return "Rufus " + DecodeVersionString(peerid[0:2])

    # BitComet/BitLord/BitVampire/Modded FUTB BitComet 
    if peerid[:4] == "exbc" or peerid[1:4] == "UTB":
        if peerid[:4] == "FUTB":
            return "BitComet Mod1 " + DecodeVersionString(peerid[4:6])
        elif peerid[:4] == "xUTB":
            return "BitComet Mod2 " + DecodeVersionString(peerid[4:6])
        elif peerid[6:10] == "LORD":
            return "BitLord " + DecodeVersionString(peerid[4:6])
        elif peerid[6:9] == "---":
        	return "BitVampire 1.3.1"
        else:
            return "BitComet " + DecodeVersionString(peerid[4:6])  

    # Opera
    if peerid[:2] == "OP":
        return "Opera" + getOperaVersion(peerid[2:6])

    # BitMagnet 
    if peerid[2:4] == "BM":
        return "BitMagnet " + DecodeVersionString(peerid[0:2]) 

    # BTGetit
    if peerid[:2] == "BG":
        return DecodePeerId("BTGetit", peerid[2:6]) 

    # GreedBT
    if peerid[:9] == "270------":
        return "GreedBT 270"
    if peerid[:9] == "271------":
        return "GreedBT 271"

    #TorrentTopia
    if peerid[:9] == "346------":
        return "TorrentTopia" 

    # Plus
    if peerid[:4] == "Plus":
        return "Plus! II"

    # XanTorrent 
    if peerid[:10] == "DansClient":
        return "XanTorrent" 

    # TorrenTres
    if peerid[:5] == "XTORR":
        return "TorrenTres 0.0." +  peerid[7]

    # TurboBT 
    if peerid[:7] == "turbobt":
        return "TurboBT " + peerid[7:10]
    
    # eXeem beta            
    if peerid[:3] == "-eX":
        version_str = ""
        version_str += str(int(peerid[3], 16)) + '.'
        version_str += str(int(peerid[4], 16))
        return "eXeem " + version_str

    # eXeem beta .21            
    if peerid[:2] == "eX":
        return "eXeem"

    #Shareaza 
    shareaza = True
    for c in peerid[:15]:
        if c == chr(0):
            shareaza = False
            break
    for i in range(16,len(peerid)):
        if shareaza:
             if ord(peerid[i]) != (ord(peerid[i % 16]) ^ ord(peerid[15 - (i % 16)])):
                shareaza = False
                break
    if shareaza:
        return "Shareaza"

    #Deadman client 
    if peerid[:7] == "Deadman" or peerid[:5] == "BTDWV":
        return "Deadman"

    #Ruby Torrent 
    if peerid[:7] == "rubytor":
        version_str = str(ord(peerid[7]))
        return "Ruby Torrent v" + version_str

    # Other
    if peerid[:4] == "bt":
        return "BT Protocol Daemon" + peerid[4:7]
    if peerid[:5].lower() == "btuga" or peerid[:5] == "oernu":
        return "BTugaXP"
    if peerid[:5] == "btfans":
        return "SimpleBT"
    if peerid[:7] == "martini":
        return "Martini Man"
    
    # Unknown peerid
    return peerid[:13]
